/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.pig.pigpen.editor.textEditor.errorHandler;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.pig.PigServer;
import org.apache.pig.impl.logicalLayer.parser.ParseException;
import org.apache.pig.pigpen.ConsoleLogger;
import org.apache.pig.pigpen.editor.PigPenEditor;
import org.apache.pig.pigpen.util.PigServerPool;
import org.apache.pig.tools.grunt.GruntParser;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.ui.texteditor.MarkerUtilities;

public class PigValidatorAndMarker {

    private String[] queries;
    private PigServer pigServer;
    IFile file;
    IDocument document;

    public static final String ERROR_MARKER_ID = "pigscript.error";

    private List<PigValidationError> errorList = new ArrayList<PigValidationError>();

    ConsoleLogger logger = ConsoleLogger.getDefault();

    public PigValidatorAndMarker(IDocument doc, IFile file) {
        this.document = doc;
        // this.queries = splitQuery(doc.get());
        this.queries = doc.get().split(";");
        this.file = file;
        this.pigServer = PigServerPool.getPigServer();

        removeExistingMarkers();
        // parsePigScript();
        parsePig();

    }

    public void removeExistingMarkers() {
        try {
            file.deleteMarkers(ERROR_MARKER_ID, true, IResource.DEPTH_ZERO);
        } catch (CoreException e) {
            logger.error(e.getMessage());
        }
    }

    private void handleError(Exception e, int lineNumber) {
        PigValidationError error = nextError(e, lineNumber);
        errorList.add(error);
    }

    protected PigValidationError nextError(Exception e, int lineNumber) {
        String error = e.getMessage();
        logger.error("Error on line " + lineNumber + ": " + error);

        PigValidationError validationError = new PigValidationError();
        validationError.setErrorMessage(error);
        validationError.setLineNumber(lineNumber);

        markError(validationError);

        return validationError;
    }

    private void markError(PigValidationError error) {
        Map map = new HashMap();

        int line = error.getLineNumber();

        // MarkerUtilities.setLineNumber(map, line);
        // MarkerUtilities.setMessage(map, error.getErrorMessage());
        map.put(IMarker.MESSAGE, error.getErrorMessage());
        map.put(IMarker.LOCATION, file.getFullPath().toString());
        try {
            map.put(IMarker.CHAR_START, document.getLineOffset(line - 1));
            map.put(IMarker.CHAR_END, document.getLineOffset(line) - 1);
        } catch (BadLocationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        map.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_ERROR));
        try {
            MarkerUtilities.createMarker(file, map, ERROR_MARKER_ID);
        } catch (CoreException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    public List getErrorList() {
        return errorList;
    }

    private void parsePigScript() {
        int line = 1;
        for (int i = 0; i < queries.length; i++) {
            String query = queries[i].trim();

            if (query.toLowerCase().startsWith("illustrate")
                    || query.toLowerCase().startsWith("describe")
                    || query.toLowerCase().startsWith("store")
                    || "\n".equals(query) || "".equals(query)) {
                line++;
                continue;
            } else {
                try {
                    line++;
                    pigServer.registerQuery(query + ";");
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    // e.printStackTrace();
                    // System.out.println("Error being handled!");
                    handleError(e, line);
                }
            }
        }
    }

    private void parsePig() {

        InputStream in;
        try {
        	String script=cleanScript(document.get());
            in = new ByteArrayInputStream(script.getBytes("UTF-8"));
            GruntParser parser = new GruntParser(in, "UTF-8");
            parser.setParams(pigServer);
            parser.parseStopOnError();
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            if (e.getCause() != null && e.getCause() instanceof ParseException) {
                ParseException ex = (ParseException) e.getCause();
                if (ex.currentToken != null)
                    handleError(ex, ex.currentToken.next.beginLine);
                else
                    logger.error(ex.getMessage());
            }

        } catch (org.apache.pig.tools.pigscript.parser.ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            System.out
                    .println("\t\tThe other parseException is being called!!!!\n\n");
        }

    }

    /**
     * remove dump and store query
     * 
     * @param string
     * @return
     */
	private String cleanScript(String content) {
		String[] lines=content.split("\n");
		StringBuilder builder=new StringBuilder();
		for (String line : lines){
			if (line.trim().toLowerCase().startsWith("dump") || 
					line.trim().toLowerCase().startsWith("store")){
				continue;
			}
			builder.append(line+"\n");	
		}
		return builder.toString();
	}

    // private String[] splitQuery(String queries) {
    // //tries to split the query on new-lines to preserve the line numbers
    // int start = 0;
    // List<String> ret = new ArrayList<String>();
    // for(int i = 0; i < queries.length(); i++) {
    // if(queries.charAt(i) == '\n') {
    // ret.add(queries.substring(start, i));
    // start = i;
    // }
    // }
    // String[] result = new String[ret.size()];
    // for(int i = 0; i < ret.size(); i++) {
    // result[i] = ret.get(i);
    // }
    // return result;
    //        
    // }
    //    
    // private int countNewLines(String str) {
    // int result = 0;
    // for(int i = 0; i < str.length(); i++) {
    // if(str.charAt(i) == '\n')
    // result ++;
    // }
    // return result;
    // }

    // private void parsePig() {
    // String[] q = document.get().split("\n");
    //        
    // int startLine = 0;
    // while(startLine < q.length) {
    // if(q[startLine].toLowerCase().startsWith("illustrate") ||
    // q[startLine].toLowerCase().startsWith("describe") ||
    // q[startLine].toLowerCase().startsWith("store") ||
    // "".equals(q[startLine].trim())) {
    // startLine++;
    // continue;
    // }
    // int end = startLine;
    // StringBuffer query = new StringBuffer();
    // do {
    // query.append(q[end]);
    // } while(!q[end++].trim().endsWith(";"));
    // try {
    // pigServer.registerQuery(query.toString());
    // } catch (IOException e) {
    // handleError(e, startLine);
    // }
    // startLine = end;
    // }
    //        
    // }

}
